<!DOCTYPE HTML>
<html lang="zh-Hans" class="sidebar-visible no-js light">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>An unsafe tour of Rust&#x27;s Send and Sync - Rust 优秀博文</title>


        <!-- Custom HTML head -->
        
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        <link rel="icon" href="../../favicon.svg">
        <link rel="shortcut icon" href="../../favicon.png">
        <link rel="stylesheet" href="../../css/variables.css">
        <link rel="stylesheet" href="../../css/general.css">
        <link rel="stylesheet" href="../../css/chrome.css">
        <link rel="stylesheet" href="../../css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="../../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../../fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../../highlight.css">
        <link rel="stylesheet" href="../../tomorrow-night.css">
        <link rel="stylesheet" href="../../ayu-highlight.css">

        <!-- Custom theme stylesheets -->

    </head>
    <body>
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "../../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">1.</strong> 类型系统</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../01_类型系统/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow.html"><strong aria-hidden="true">1.1.</strong> Rust Concept Clarification Deref vs AsRef vs Borrow vs Cow</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow/Deref_AsRef_Borrow_Cow释义.html"><strong aria-hidden="true">1.2.</strong> Deref AsRef Borrow Cow 释义</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然.html"><strong aria-hidden="true">1.3.</strong> Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust的Cow类型有什么用？详解Cow及其用途/Rust的Cow类型有什么用？详解Cow及其用途.html"><strong aria-hidden="true">1.4.</strong> Rust的Cow类型有什么用？详解Cow及其用途</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/判别Fn、FnMut、FnOnce的标准/判别Fn、FnMut、FnOnce的标准.html"><strong aria-hidden="true">1.5.</strong> 判别Fn、FnMut、FnOnce的标准</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/一行代码告诉你内部可变性的真相(UnsafeCell)/一行代码告诉你内部可变性的真相(UnsafeCell).html"><strong aria-hidden="true">1.6.</strong> 一行代码告诉你内部可变性的真相(UnsafeCell)</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Tour_of_Rust's_Standard_Library_Traits/Tour_of_Rust's_Standard_Library_Traits.html"><strong aria-hidden="true">1.7.</strong> Tour of Rust's Standard Library Traits</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/逆变、协变与子类型，以及Rust/逆变、协变与子类型，以及Rust.html"><strong aria-hidden="true">1.8.</strong> 逆变、协变与子类型，以及Rust</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust自引用结构、Pin与Unpin/Rust自引用结构、Pin与Unpin.html"><strong aria-hidden="true">1.9.</strong> Rust自引用结构、Pin与Unpin</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/为什么Rust需要Pin,Unpin/为什么Rust需要Pin,Unpin.html"><strong aria-hidden="true">1.10.</strong> 译：为什么 Rust 需要 Pin, Unpin ？</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/定海神针Pin和Unpin/定海神针Pin和Unpin.html"><strong aria-hidden="true">1.11.</strong> 译：定海神针 Pin 和 Unpin</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/sizedness-in-rust/sizedness-in-rust.html"><strong aria-hidden="true">1.12.</strong> Sizedness in Rust</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust生命周期集大成者PhantomData〈T〉/Rust生命周期集大成者PhantomData〈T〉.html"><strong aria-hidden="true">1.13.</strong> Rust生命周期集大成者 PhantomData&lt;T&gt;</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用Rust做类型体操_Part_0.html"><strong aria-hidden="true">1.14.</strong> 数据库表达式执行的黑魔法：用Rust做类型体操 Part 0</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：GAT实现引用类型关联_Part_1.html"><strong aria-hidden="true">1.15.</strong> 数据库表达式执行的黑魔法：GAT实现引用类型关联 Part 1</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用HRTB写bound_Part_2.html"><strong aria-hidden="true">1.16.</strong> 数据库表达式执行的黑魔法：用HRTB写bound Part 2</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用Rust做类型体操之用宏展开重复代码_Part_3_&_4.html"><strong aria-hidden="true">1.17.</strong> 数据库表达式执行的黑魔法：用Rust做类型体操之用宏展开重复代码 Part 3 & 4</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：与Rust编译器斗智斗勇之表达式向量化_Part_5_&_6.html"><strong aria-hidden="true">1.18.</strong> 数据库表达式执行的黑魔法：与Rust编译器斗智斗勇之表达式向量化 Part 5 & 6</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：在Rust中用宏关联逻辑类型和实际类型_Part_7.html"><strong aria-hidden="true">1.19.</strong> 数据库表达式执行的黑魔法：在Rust中用宏关联逻辑类型和实际类型 Part 7</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">2.</strong> 生命周期</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../02_生命周期/Rust中的生命周期——从StrSplit实例说开去/Rust中的生命周期——从StrSplit实例说开去.html"><strong aria-hidden="true">2.1.</strong> Rust中的生命周期——从StrSplit实例说开去</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/与ChatGPT深度对话来学Rust生命周期/与ChatGPT深度对话来学Rust生命周期.html"><strong aria-hidden="true">2.2.</strong> 与ChatGPT深度对话来学Rust生命周期</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——early_bound与late_bound（1）/进击的Rust生命周期——early_bound与late_bound（1）.html"><strong aria-hidden="true">2.3.</strong> 进击的Rust生命周期——early_bound与late_bound（1）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——early_bound与late_bound（2）/进击的Rust生命周期——early_bound与late_bound（2）.html"><strong aria-hidden="true">2.4.</strong> 进击的Rust生命周期——early_bound与late_bound（2）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——一力降十会的MIR（1）/进击的Rust生命周期——一力降十会的MIR（1）.html"><strong aria-hidden="true">2.5.</strong> 进击的Rust生命周期——一力降十会的MIR（1）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——一力降十会的MIR（2）/进击的Rust生命周期——一力降十会的MIR（2）.html"><strong aria-hidden="true">2.6.</strong> 进击的Rust生命周期——一力降十会的MIR（2）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/Common_Rust_Lifetime_Misconceptions/Common_Rust_Lifetime_Misconceptions.html"><strong aria-hidden="true">2.7.</strong> Common Rust Lifetime Misconceptions</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/Rust生命周期常见误区/Rust生命周期常见误区.html"><strong aria-hidden="true">2.8.</strong> 译：Rust生命周期常见误区</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">3.</strong> 无畏并发</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../05_无畏并发/简单写个Rust无锁队列/简单写个Rust无锁队列.html"><strong aria-hidden="true">3.1.</strong> 简单写个Rust无锁队列</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/进击的Rust多线程——混合自旋锁/进击的Rust多线程——混合自旋锁.html"><strong aria-hidden="true">3.2.</strong> 进击的Rust多线程——混合自旋锁</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/An_unsafe_tour_of_Rust's_Send_and_Sync/An_unsafe_tour_of_Rust's_Send_and_Sync.html" class="active"><strong aria-hidden="true">3.3.</strong> An unsafe tour of Rust's Send and Sync</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/进击的Rust多线程——Send与Sync/进击的Rust多线程——Send与Sync.html"><strong aria-hidden="true">3.4.</strong> 进击的Rust多线程——Send与Sync</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/进击的Rust多线程——离经叛道的PhantomData/进击的Rust多线程——离经叛道的PhantomData.html"><strong aria-hidden="true">3.5.</strong> 进击的Rust多线程——离经叛道的PhantomData</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/Rust_Async_Pin概念解析/Rust_Async_Pin概念解析.html"><strong aria-hidden="true">3.6.</strong> Rust Async: Pin概念解析</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/Rust和C++的并发库对比/Rust和C++的并发库对比.html"><strong aria-hidden="true">3.7.</strong> 译：Rust 和 C++ 的并发库对比</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/Rust原子类型和内存排序/Rust原子类型和内存排序.html"><strong aria-hidden="true">3.8.</strong> Rust原子类型和内存排序</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">4.</strong> 网络编程</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../06_网络编程/从编解码层面理解WebSocket_手写一个WebSocket/从编解码层面理解WebSocket_手写一个WebSocket.html"><strong aria-hidden="true">4.1.</strong> 从编解码层面理解WebSocket 手写一 个WebSocket</a></li><li class="chapter-item expanded "><a href="../../06_网络编程/透过Rust探索系统的本原：网络篇/透过Rust探索系统的本原：网络篇.html"><strong aria-hidden="true">4.2.</strong> 透过Rust探索系统的本原：网络篇</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">5.</strong> 轮子系列</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../07_轮子系列/700行Rust写一个内存分配器/700行Rust写一个内存分配器.html"><strong aria-hidden="true">5.1.</strong> 700行Rust写一个内存分配器</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/Rust：网络库的实现思路/Rust：网络库的实现思路.html"><strong aria-hidden="true">5.2.</strong> Rust：网络库的实现思路</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/Rust异步运行时基础部件/Rust异步运行时基础部件.html"><strong aria-hidden="true">5.3.</strong> Rust异步运行时基础部件</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/使用Rust+epoll编写异步IO框架/使用Rust+epoll编写异步IO框架（1）.html"><strong aria-hidden="true">5.4.</strong> 使用Rust+epoll编写异步IO框架（1）</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/使用Rust+epoll编写异步IO框架/使用Rust+epoll编写异步IO框架（2）.html"><strong aria-hidden="true">5.5.</strong> 使用Rust+epoll编写异步IO框架（2）</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/使用Rust+epoll编写异步IO框架/使用Rust+epoll编写异步IO框架（3）.html"><strong aria-hidden="true">5.6.</strong> 使用Rust+epoll编写异步IO框架（3）</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day1.html"><strong aria-hidden="true">5.7.</strong> 用rust从零开发一套web框架：day1</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day2.html"><strong aria-hidden="true">5.8.</strong> 用rust从零开发一套web框架：day2</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day3.html"><strong aria-hidden="true">5.9.</strong> 用rust从零开发一套web框架：day3</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day4.html"><strong aria-hidden="true">5.10.</strong> 用rust从零开发一套web框架：day4</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day5.html"><strong aria-hidden="true">5.11.</strong> 用rust从零开发一套web框架：day5</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">6.</strong> 奇技淫巧</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../08_奇技淫巧/Copy-On-Write是不是优化？/Copy-On-Write是不是优化？.html"><strong aria-hidden="true">6.1.</strong> 译：Copy-On-Write是不是优化？</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/揭秘神奇的Rust_Axum风格的函数实现/揭秘神奇的Rust_Axum风格的函数实现.html"><strong aria-hidden="true">6.2.</strong> 译：揭秘神奇的 Rust Axum 风格的函数实现</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/“变长参数”函数与回调/“变长参数”函数与回调.html"><strong aria-hidden="true">6.3.</strong> “变长参数”函数与回调</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/Rust字符串格式化的幕后：format_args!()/Rust字符串格式化的幕后：format_args!().html"><strong aria-hidden="true">6.4.</strong> 译：Rust字符串格式化的幕后：format_args!()</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/给Rust带来一点C++特产/给Rust带来一点C++特产.html"><strong aria-hidden="true">6.5.</strong> 给Rust带来一点C++特产</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/一步步实现_Rust_Bevy_ECS_的_System_简化版本/一步步实现_Rust_Bevy_ECS_的_System_简化版本.html"><strong aria-hidden="true">6.6.</strong> 一步步实现 Rust Bevy ECS 的 System 简化版本</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/Exploring_Design_Patterns_in_Rust_with_Algorithmic_Trading_Examples/Exploring_Design_Patterns_in_Rust_with_Algorithmic_Trading_Examples.html"><strong aria-hidden="true">6.7.</strong> Exploring Design Patterns in Rust with Algorithmic Trading Examples</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">7.</strong> 源码分析</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../09_源码分析/Rust并发：bytes源码分析/Rust并发：bytes源码分析.html"><strong aria-hidden="true">7.1.</strong> Rust并发：bytes源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust并发：标准库Arc源码分析/Rust并发：标准库Arc源码分析.html"><strong aria-hidden="true">7.2.</strong> Rust并发：标准库Arc源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust并发：标准库sync_Once源码分析/Rust并发：标准库sync_Once源码分析.html"><strong aria-hidden="true">7.3.</strong> Rust并发：标准库sync::Once源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust源码阅读：引用计数Rc/Rust源码阅读：引用计数Rc.html"><strong aria-hidden="true">7.4.</strong> Rust源码阅读：引用计数Rc</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust源码阅读：Cell、RefCell与内部可变性/Rust源码阅读：Cell、RefCell与内部可变性.html"><strong aria-hidden="true">7.5.</strong> Rust源码阅读： Cell、RefCell与内部可变性</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/关于_Rust_的_UnsafeCell、Cell_与_RefCell/关于_Rust_的_UnsafeCell、Cell_与_RefCell.html"><strong aria-hidden="true">7.6.</strong> 关于 Rust 的 UnsafeCell、Cell 与 RefCell</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust_Async_async-stream源码分析/Rust_Async_async-stream源码分析.html"><strong aria-hidden="true">7.7.</strong> Rust Async: async-stream源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/走进Tokio的异步世界/走进Tokio的异步世界.html"><strong aria-hidden="true">7.8.</strong> 走进 Tokio 的异步世界</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/tokio.rs_runtime的实现/tokio.rs_runtime的实现.html"><strong aria-hidden="true">7.9.</strong> tokio.rs runtime 的实现</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Tokio_internals/Tokio_internals.html"><strong aria-hidden="true">7.10.</strong> Tokio internals</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Tokio_internals/译文：Tokio內部机制.html"><strong aria-hidden="true">7.11.</strong> 译：Tokio 内部机制</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust_Axum_HTTP_框架的架构分析/Rust_Axum_HTTP_框架的架构分析.html"><strong aria-hidden="true">7.12.</strong> Rust Axum HTTP 框架的架构分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/安利一个Rust_Game_Engine：Bevy--ECS部分/安利一个Rust_Game_Engine：Bevy--ECS部分.html"><strong aria-hidden="true">7.13.</strong> 安利一个Rust Game Engine：Bevy--ECS部分</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Tokio_解析之任务调度/Tokio_解析之任务调度.html"><strong aria-hidden="true">7.14.</strong> Tokio 解析之任务调度</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">8.</strong> 生态观察</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../11_生态观察/Rust_web_frameworks_have_subpar_error_reporting/Rust_web_frameworks_have_subpar_error_reporting.html"><strong aria-hidden="true">8.1.</strong> Rust web frameworks have subpar error reporting</a></li><li class="chapter-item expanded "><a href="../../11_生态观察/SeaORM：要做Rust版本的ActiveRecord/SeaORM：要做Rust版本的ActiveRecord.html"><strong aria-hidden="true">8.2.</strong> SeaORM：要做Rust版本的ActiveRecord</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">9.</strong> 死灵终极</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_总述.html"><strong aria-hidden="true">9.1.</strong> 译：Learn Rust the Dangerous Way 总述</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_0.html"><strong aria-hidden="true">9.2.</strong> 译：Learn Rust the Dangerous Way 0</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_1.html"><strong aria-hidden="true">9.3.</strong> 译：Learn Rust the Dangerous Way 1</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_2.html"><strong aria-hidden="true">9.4.</strong> 译：Learn Rust the Dangerous Way 2</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_3.html"><strong aria-hidden="true">9.5.</strong> 译：Learn Rust the Dangerous Way 3</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_4.html"><strong aria-hidden="true">9.6.</strong> 译：Learn Rust the Dangerous Way 4</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_5.html"><strong aria-hidden="true">9.7.</strong> 译：Learn Rust the Dangerous Way 5</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测（一）.html"><strong aria-hidden="true">9.8.</strong> Unsafe Rust 随堂小测（一）</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测（二）.html"><strong aria-hidden="true">9.9.</strong> Unsafe Rust 随堂小测（二）</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测（三）.html"><strong aria-hidden="true">9.10.</strong> Unsafe Rust 随堂小测（三）</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测参考答案.html"><strong aria-hidden="true">9.11.</strong> Unsafe Rust 随堂小测参考答案</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky bordered">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">Rust 优秀博文</h1>

                    <div class="right-buttons">
                        <a href="../../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="an-unsafe-tour-of-rusts-send-and-sync"><a class="header" href="#an-unsafe-tour-of-rusts-send-and-sync">An unsafe tour of Rust's Send and Sync</a></h1>
<p>作者：nyanpasu64</p>
<p>原载：<a href="https://nyanpasu64.gitlab.io/blog/an-unsafe-tour-of-rust-s-send-and-sync">https://nyanpasu64.gitlab.io/blog/an-unsafe-tour-of-rust-s-send-and-sync</a></p>
<p><em>Written by</em> nyanpasu64
<em>on</em> January 1, 2021</p>
<p>Rust's concurrency safety is based around the <code>Send</code> and <code>Sync</code> traits. For people writing safe code, you don't really need to understand these traits on a deep level, only enough to satisfy the compiler when it spits errors at you (or switch from <code>std</code> threads to Crossbeam scoped threads to make errors go away). However if you're writing unsafe concurrent code, such as having a <code>&amp;UnsafeCell&lt;T&gt;</code> hand out <code>&amp;T</code> and <code>&amp;mut T</code>, you need to understand <code>Send</code> and <code>Sync</code> at a more fundamental level, to pick the appropriate trait bounds when writing <code>unsafe impl Send/Sync</code> statements, or add the appropriate <code>PhantomData&lt;T&gt;</code> to your types.</p>
<p>In this article, I will explore the precise behavior of <code>Send</code> and <code>Sync</code>, and explain <em>why</em> the standard library's trait bounds are the way they are.</p>
<h2 id="prior-art"><a class="header" href="#prior-art">Prior art</a></h2>
<blockquote>
<p>You can think of Send as &quot;Exclusive access is thread-safe,&quot; and Sync as &quot;Shared access is thread-safe.&quot;</p>
<p>[<a href="https://www.reddit.com/r/rust/comments/9elom2/why_does_implt_send_for_mut_t_require_t_send/">Source]</a></p>
</blockquote>
<p>I recommended first reading <a href="https://limpet.net/mbrubeck/2019/02/07/rust-a-unique-perspective.html">&quot;Rust: A unique perspective&quot;</a>. This article gives a conceptual overview of the mechanics (unique and shared references) I will analyze in more depth.</p>
<h2 id="defining-sync-and-send"><a class="header" href="#defining-sync-and-send">Defining Sync and Send</a></h2>
<p><code>T: Send</code> means <code>T</code> and <code>&amp;mut T</code> (which allow dropping <code>T</code>) can be passed between threads. <code>T: Sync</code> means <code>&amp;T</code> (which allows shared/aliased access to <code>T</code>) can be passed between threads. Either or both may be true for any given type. <code>T: Sync</code> ≡ <code>&amp;T: Send</code> (by definition).</p>
<p>One way that <code>T: !Sync</code> can occur is <strong>if a type has non-atomic interior mutability</strong>. This means that every <code>&amp;T</code> (there can be more than one) can mutate <code>T</code> at the same time non-atomically, causing data races if a <code>&amp;T</code> is sent to another thread. <code>T: !Sync</code> includes <code>Cell&lt;V&gt;</code> and <code>RefCell&lt;V&gt;</code>, as well as <code>Rc&lt;V&gt;</code> (which acts like <code>&amp;(Cell&lt;RefCount&gt;, V)</code>).</p>
<p><code>T: !Send</code> <strong>if a type is bound to the current thread</strong>. Examples:</p>
<ul>
<li><code>MutexGuard</code>, where the &quot;unlock&quot; syscall must occur on the same thread as &quot;lock&quot;.</li>
<li><code>&amp;V</code> where <code>V</code> can be modified non-atomically (only safe from a single thread) through multiple <code>&amp;V</code> (explained above).</li>
</ul>
<h2 id="primitives"><a class="header" href="#primitives">Primitives</a></h2>
<p>Most primitive types (like <code>i32</code>) are <code>Send+Sync</code>. They can be read through shared references (<code>&amp;</code>) by multiple threads at once (<code>Sync</code>), and modified through unique references (<code>&amp;mut</code>) by any one thread at a time (<code>Send</code>).</p>
<h2 id="owning-references"><a class="header" href="#owning-references">Owning references</a></h2>
<p><code>Box&lt;T&gt;</code> and <code>&amp;mut T</code> give the same access as having a <code>T</code> directly, so it shares the same Sync/Send status as <code>T</code>.</p>
<p>(Sidenote) Technically, <code>&amp;mut T</code> allows swapping the <code>T</code> (which cannot panic), but prohibits moving the <code>T</code>. This is because moving invalidates the <code>&amp;mut T</code>, and the <code>&amp;mut T</code>s and <code>T</code> it's constructed from.</p>
<p>For a demonstration of <code>&amp;mut T</code>, see <a href="https://nyanpasu64.gitlab.io/blog/an-unsafe-tour-of-rust-s-send-and-sync/#example-passing-mut-t-send-between-threads">&quot;Example: Passing <code>&amp;mut (T: Send)</code> between threads&quot;</a> section in this page.</p>
<h3 id="where-these-semantics-are-defined"><a class="header" href="#where-these-semantics-are-defined">Where these semantics are defined</a></h3>
<ul>
<li><a href="https://doc.rust-lang.org/std/primitive.reference.html#impl-Send-1"><code>impl Send for &amp;mut T where T: Send</code></a></li>
<li><code>impl Sync for &amp;mut T where T: Sync</code> is not on the page...</li>
<li><a href="https://doc.rust-lang.org/std/boxed/struct.Box.html#impl-Send"><code>impl Send for Box where T: Send</code></a></li>
<li><a href="https://doc.rust-lang.org/std/boxed/struct.Box.html#impl-Sync"><code>impl Sync for Box where T: Sync</code></a></li>
</ul>
<h2 id="shared-references"><a class="header" href="#shared-references">Shared references</a></h2>
<p>Unlike owning references, many <code>&amp;T</code> can be created from the same <code>T</code>. And an unlimited number of <code>&amp;T</code> and <code>Rc&lt;T&gt;</code> and <code>Arc&lt;T&gt;</code> copies/clones can point to the same <code>T</code>.</p>
<p>By definition, you can <code>Send</code> <code>&amp;T</code> instances to other threads iff <code>T</code> is <code>Sync</code>. For example, <code>&amp;i32</code> is <code>Send</code> because <code>i32</code> is <code>Sync</code>.</p>
<p>Less obvious is that <code>&amp;T: Sync</code> requires that <code>T: Sync</code>. Why is this the case?</p>
<ul>
<li>Why must <code>T</code> be <code>Sync</code>? We want <code>&amp;T: Sync</code>. This means <code>&amp;&amp;T</code> (which is clonable/copyable) is <code>Send</code>, allowing multiple threads to concurrently obtain <code>&amp;&amp;T</code> and <code>&amp;T</code>, which is only legal if <code>T: Sync</code>.</li>
<li>Why is <code>&amp;&amp;T: Send</code> legal? Because <code>&amp;T</code> lacks interior mutability (a <code>&amp;&amp;T</code> can't modify the <code>&amp;T</code> to point to a different <code>T</code>).</li>
</ul>
<h3 id="sources"><a class="header" href="#sources">Sources</a></h3>
<ul>
<li>
<p><a href="https://doc.rust-lang.org/std/primitive.reference.html#impl-Send"><code>impl Send for &amp;T where T: Sync</code></a></p>
</li>
<li>
<pre><code>impl Sync for &amp;T where T: Sync
</code></pre>
<p>is not on the page...</p>
<ul>
<li>For a demonstration, see the <a href="https://nyanpasu64.gitlab.io/blog/an-unsafe-tour-of-rust-s-send-and-sync/#example-t-send-or-sync-both-depend-on-t-sync">&quot;Example: <code>&amp;T: Send or Sync</code> both depend on <code>T: Sync</code>&quot;</a> section in this page.</li>
</ul>
</li>
</ul>
<h2 id="interior-mutability"><a class="header" href="#interior-mutability">Interior mutability</a></h2>
<p><code>Cell&lt;i32&gt;</code> (and <code>RefCell&lt;i32&gt;</code>) is <code>!Sync</code> because it has single-threaded <strong>interior mutability</strong>, which translates to multithreaded <strong>data races</strong>.</p>
<p><code>UnsafeCell&lt;i32&gt;</code> is <code>!Sync</code> to prevent misuse, since only some usages are <code>Sync</code> and <code>impl !Sync</code> is unstable. As a result, you need to <code>unsafe impl Sync</code> (which shows up in grep) if you want concurrent access.</p>
<h2 id="smart-pointers-rct"><a class="header" href="#smart-pointers-rct">Smart pointers: <code>Rc&lt;T&gt;</code></a></h2>
<p><code>Rc&lt;i32&gt;</code> acts like <code>&amp;(Cell&lt;RefCount&gt;, i32)</code>. It is <code>!Sync</code> because <code>Cell&lt;RefCount&gt;</code> has <strong>interior mutability</strong> and <strong>data races</strong> on <code>RefCount</code>, and <code>!Send</code> because <code>Rc&lt;T&gt;</code> is clonable, acts like a<code>&amp;Cell&lt;RefCount&gt;</code>, and <code>Cell&lt;RefCount&gt;</code> is <code>!Sync</code>.</p>
<p>(Technically <code>Rc&lt;i32&gt;</code> also acts like <code>&amp;mut T</code> in its ability to drop <code>T</code>, but it doesn't matter because it's always <code>!Send</code> and <code>!Sync</code>.)</p>
<h3 id="sources-1"><a class="header" href="#sources-1">Sources</a></h3>
<ul>
<li><a href="https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-Send"><code>impl !Send for Rc</code></a></li>
<li><a href="https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-Sync"><code>impl !Sync for Rc</code></a></li>
</ul>
<h2 id="smart-pointers-arct-atomic-refcounting"><a class="header" href="#smart-pointers-arct-atomic-refcounting">Smart pointers: <code>Arc&lt;T&gt;</code> (atomic refcounting)</a></h2>
<p><code>Arc&lt;T&gt;</code> is a doozy. It acts like <code>&amp;(Atomic&lt;RefCount&gt;, T)</code> in its ability to alias <code>T</code>, and <code>T</code>/<code>&amp;mut T</code> in its ability to drop or <code>get_mut</code> or <code>try_unwrap</code> the <code>T</code>.</p>
<p>Because <code>&amp;T</code> can alias, <code>Arc&lt;T&gt;: Send+Sync</code> requires <code>T: Sync</code>.</p>
<p>Additionally, <code>Arc&lt;T&gt;: Send</code> requires <code>T: Send</code> (because you can move <code>Arc&lt;T&gt;</code> across threads, and <code>T</code> with it).</p>
<p>And <code>Arc&lt;T&gt;: Sync</code> requires <code>T: Send</code>, because if <code>T: !Send</code> but <code>Arc&lt;T&gt;: Sync</code>, you could clone the Arc (via <code>&amp;Arc&lt;T&gt;</code>) from another thread, and drop (or <code>get_mut</code> or <code>try_unwrap</code>) the clone last, violating <code>T: !Send</code>.</p>
<p>(<code>Atomic&lt;RefCount&gt;</code> is <code>Send+Sync</code> and does not contribute to <code>Arc</code>'s thread safety.)</p>
<h3 id="sources-2"><a class="header" href="#sources-2">Sources</a></h3>
<ul>
<li><a href="https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send"><code>impl Send for Arc where T: Send + Sync</code></a></li>
<li><a href="https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Sync"><code>impl Sync for Arc where T: Send + Sync</code></a></li>
</ul>
<p>This was also discussed in a <a href="https://stackoverflow.com/questions/41909811/why-does-arct-require-t-to-be-both-send-and-sync-in-order-to-be-send">Stack Overflow question</a>.</p>
<h2 id="mutexes"><a class="header" href="#mutexes">Mutexes</a></h2>
<p><code>Mutex&lt;T&gt;</code> is <code>Sync</code> even if <code>T</code> isn't, because if multiple threads obtain <code>&amp;Mutex&lt;T&gt;</code>, they can't all obtain <code>&amp;T</code>.</p>
<p><code>Mutex&lt;T&gt;: Sync</code> requires <code>T: Send</code>. We want <code>&amp;Mutex</code> to be <code>Send</code>, meaning multiple threads can lock the mutex and obtain a <code>&amp;mut T</code> (which lets you swap <code>T</code> and control which thread calls <code>Drop</code>). To hand-wave, exclusive access to <code>T</code> gets passed between threads, requiring that <code>T: Send</code>.</p>
<p><code>Mutex&lt;T&gt;: Send</code> requires <code>T: Send</code> because <code>Mutex</code> is a value type.</p>
<p><code>MutexGuard&lt;T&gt;</code> is <code>!Send</code> because it's <strong>bound to the constructing thread</strong> (on some OSes including Windows, you can't send or exchange &quot;responsibility for freeing a mutex&quot; to another thread). Otherwise it acts like a <code>&amp;mut T</code>, which is <code>Sync</code> if T is <code>Sync</code>. Additionally you can extract a <code>&amp;mut T</code> (which is <code>Send</code>) using <code>&amp;mut *guard</code>.</p>
<h3 id="sources-3"><a class="header" href="#sources-3">Sources</a></h3>
<ul>
<li><a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html#impl-Send"><code>Mutex</code> traits</a></li>
<li><a href="https://doc.rust-lang.org/std/sync/struct.MutexGuard.html#impl-Send"><code>MutexGuard</code> traits</a></li>
</ul>
<h3 id="contrived-corner-cases"><a class="header" href="#contrived-corner-cases">Contrived corner cases</a></h3>
<p><code>Mutex&lt;MutexGuard&lt;i32&gt;&gt;</code> is <code>!Sync</code> because <code>MutexGuard&lt;i32&gt;</code> is <code>!Send</code>.</p>
<h2 id="thoughts-on-trait-bounds-and-flexibility-for-users"><a class="header" href="#thoughts-on-trait-bounds-and-flexibility-for-users">Thoughts on trait bounds and flexibility for users</a></h2>
<p>Why does <code>Arc&lt;T&gt;</code> not have a <code>where T: Send + Sync</code> trait bound, but instead allows you to construct <code>Arc&lt;T&gt;</code> for any <code>T</code> (but just not send/share it across threads)?</p>
<p>I've heard that you should avoid putting trait bounds in types, but (if I remember correctly) instead in method implementations, or (in the case of <code>Arc</code>) in conditional <code>Send</code>/<code>Sync</code> implementations. One person said:</p>
<blockquote>
<p>The reason the restrictions are usually on the implementations rather than on the type in general is that you don't usually know every possible implementation If you later realize you can add other functionality, you can just add additional impl blocks with different restrictions, whereas if they were on the type you would potentially have to worry about unifying the restrictions (which can be really awkward) or removing them altogether</p>
</blockquote>
<p>When asking about this topic, I was pointed to the <a href="https://rust-lang.github.io/api-guidelines/about.html">Rust API guidelines</a>, but I couldn't find any discussion of this issue.</p>
<hr />
<p>I personally encountered this topic when I used an <code>Arc</code> internally for <a href="https://github.com/nyanpasu64/spectro2/blob/master/flip-cell/src/lib.rs">the <code>flip-cell</code> crate</a> (which turns out to be equivalent to <a href="https://github.com/Ralith/oddio/blob/main/src/swap.rs">Oddio's <code>Swap</code> type</a> and the <a href="https://github.com/HadrienG2/triple-buffer"><code>triple-buffer</code> crate</a>).</p>
<p><code>Arc&lt;T&gt;: Sync</code> is only safe if <code>T: Send</code>, not just <code>T: Sync</code>; this is because another thread can look at an <code>&amp;Arc&lt;T&gt;</code>, clone it, and obtain an <code>Arc&lt;T&gt;</code> sharing ownership over the same object. But if we create a type <code>FlipReader&lt;T&gt;</code> (<a href="https://github.com/nyanpasu64/spectro2/blob/05561a21d85fc5fc0e8e92140edf01d6b64401bc/flip-cell/src/lib.rs#L188-L201">source</a>) which contains an <code>Arc&lt;Wrapper&lt;T&gt;&gt;</code> but prohibits cloning it, then making <code>FlipReader&lt;T&gt;: Sync</code> does not allow another thread to take shared ownership of <code>Wrapper&lt;T&gt;</code>, so the <code>Wrapper&lt;T&gt;: Send</code> trait bound is unnecessary.</p>
<p>Had the struct <code>Arc&lt;T&gt;</code> required <code>T: Send + Sync</code> to even be constructed, <code>Arc</code> would be crippled as a building block for unsafe code.</p>
<h2 id="example-passing-mut-t-send-between-threads"><a class="header" href="#example-passing-mut-t-send-between-threads">Example: Passing <code>&amp;mut (T: Send)</code> between threads</a></h2>
<p>Cell is <code>Send</code> but not <code>Sync</code>. Both <code>Cell</code> and <code>&amp;mut Cell</code> can be passed between threads. The following code builds as-is, but not if <code>&amp;mut</code> is changed to <code>&amp;</code>.</p>
<pre><pre class="playground"><code class="language-rust">use std::thread;
use std::cell::Cell;

fn main() {
    // Send + !Sync
    let cell_ref: &amp;mut Cell&lt;i32&gt; = Box::leak(Box::new(Cell::new(0)));

    thread::spawn(move || {
        cell_ref.replace(1);
    });
}
</code></pre></pre>
<h2 id="example-t-send-or-sync-both-depend-on-t-sync"><a class="header" href="#example-t-send-or-sync-both-depend-on-t-sync">Example: <code>&amp;T: Send or Sync</code> both depend on <code>T: Sync</code></a></h2>
<p>If <code>T: !Sync</code> (for example <code>Cell</code>), then <code>&amp;T</code> is neither <code>Send</code> nor <code>Sync</code>.</p>
<pre><pre class="playground"><code class="language-rust">use std::cell::Cell;

fn ensure_sync&lt;T: Sync&gt;(_: T) {}
fn ensure_send&lt;T: Send&gt;(_: T) {}

fn main() {
    let foo = Cell::new(1i32);
    ensure_sync(&amp;foo);
    ensure_send(&amp;foo);
}
</code></pre></pre>
<p>Trying to compile this code returns the errors:</p>
<pre><code>Standard Error

   Compiling playground v0.0.1 (/playground)
error[E0277]: `Cell&lt;i32&gt;` cannot be shared between threads safely
 --&gt; src/main.rs:8:17
  |
3 | fn ensure_sync&lt;T: Sync&gt;(_: T) {}
  |                   ---- required by this bound in `ensure_sync`
...
8 |     ensure_sync(&amp;foo);
  |                 ^^^^ `Cell&lt;i32&gt;` cannot be shared between threads safely
  |
  = help: within `&amp;Cell&lt;i32&gt;`, the trait `Sync` is not implemented for `Cell&lt;i32&gt;`
  = note: required because it appears within the type `&amp;Cell&lt;i32&gt;`

error[E0277]: `Cell&lt;i32&gt;` cannot be shared between threads safely
 --&gt; src/main.rs:9:17
  |
4 | fn ensure_send&lt;T: Send&gt;(_: T) {}
  |                   ---- required by this bound in `ensure_send`
...
9 |     ensure_send(&amp;foo);
  |                 ^^^^ `Cell&lt;i32&gt;` cannot be shared between threads safely
  |
  = help: the trait `Sync` is not implemented for `Cell&lt;i32&gt;`
  = note: required because of the requirements on the impl of `Send` for `&amp;Cell&lt;i32&gt;`
</code></pre>
<p>If <code>T: !Send + Sync</code> (for example <code>MutexGuard</code>), then <code>&amp;T</code> is still <code>Send + Sync</code>. (This makes sense, because <code>T: !Send</code> only constrains the behavior of a <code>&amp;mut T</code>, and should not affect the properties of a <code>&amp;T</code>.)</p>
<pre><pre class="playground"><code class="language-rust">use std::marker::PhantomData;
use std::sync::MutexGuard;

fn ensure_sync&lt;T: Sync&gt;(_: T) {}
fn ensure_send&lt;T: Send&gt;(_: T) {}

fn main() {
    let foo = PhantomData::&lt;MutexGuard&lt;i32&gt;&gt; {};
    ensure_sync(&amp;foo);
    ensure_send(&amp;foo);
}
</code></pre></pre>
<p><em>This blog post was edited on 2021-02-09 to fix minor errors and clarify <code>Rc&lt;V&gt;</code>.</em></p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../../05_无畏并发/进击的Rust多线程——混合自旋锁/进击的Rust多线程——混合自旋锁.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next" href="../../05_无畏并发/进击的Rust多线程——Send与Sync/进击的Rust多线程——Send与Sync.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../../05_无畏并发/进击的Rust多线程——混合自旋锁/进击的Rust多线程——混合自旋锁.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next" href="../../05_无畏并发/进击的Rust多线程——Send与Sync/进击的Rust多线程——Send与Sync.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>




        <script type="text/javascript">
            window.playground_copyable = true;
        </script>


        <script src="../../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../searcher.js" type="text/javascript" charset="utf-8"></script>

        <script src="../../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->


    </body>
</html>
